package com.cctv.ldap;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.ldap.NamingException;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.AbstractContextMapper;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.ldap.filter.WhitespaceWildcardsFilter;


/**
 * 
 * @author 146
 * 
 */
public class LdapUtils {

	private static LdapTemplate	personLdapTemplate;
	private static String BASE_DN = "cn=dept,dc=cctv,dc=com";
	private static LdapTemplate	deptLdapTemplate;
	private final Log			log	= LogFactory.getLog ( getClass () );

	public void setPersonLdapTemplate(LdapTemplate personLdapTemplate) {
		LdapUtils.personLdapTemplate = personLdapTemplate;
	}

	public void setDeptLdapTemplate(LdapTemplate deptLdapTemplate) {
		LdapUtils.deptLdapTemplate = deptLdapTemplate;
	}

	static {
		try {
			new ClassPathXmlApplicationContext ( new String[] { "com/cctv/ldap/applicationContext-ldap.xml" } );
			System.out.println ( "*********************** init ldaptemplate over **********************" );
		}
		catch (Exception e) {
			System.out.println ( "*********************** init errorss: " + e.getMessage () );
		}

	}
	private static final class PersonContextMapper extends
			AbstractContextMapper {
		protected Object doMapFromContext(DirContextOperations ctx) {
			LdapPerson person = new LdapPerson ();
			person.setCn ( ctx.getStringAttribute ( "cn" ) );
			person.setSn ( ctx.getStringAttribute ( "sn" ) );
			person.setUid ( ctx.getStringAttribute ( "uid" ) );
			person.setPostalCode ( ctx.getStringAttribute ( "postalCode" ) );
			person.setInitials ( ctx.getStringAttribute ( "initials" ) );
			person.setMobile ( ctx.getStringAttribute ( "mobile" ) );
			person.setOu ( ctx.getStringAttribute ( "ou" ) );
			person.setTitle ( ctx.getStringAttribute ( "title" ) );
			person.setEmployeeType ( ctx.getStringAttribute ( "employeeType" ) );
			person.setUserPassword(new String((byte[]) ctx.getObjectAttribute("userpassword")));
			return person;
		}
	}
	private static final class DeptContextMapper extends AbstractContextMapper {
		protected Object doMapFromContext(DirContextOperations ctx) {
			LdapDept org = new LdapDept();
			org.setOu(ctx.getStringAttribute("ou"));			
			org.setPostalAddress(ctx.getStringAttribute("postalAddress"));				// 部门级别
			org.setPostalcode(ctx.getStringAttribute("postalcode"));					// 旧层次码
			org.setPostOfficeBox(ctx.getStringAttribute("postOfficeBox"));				// 上级部门
			org.setDescription(ctx.getStringAttribute("description"));					// 部门名称
			org.setStreet(ctx.getStringAttribute("street"));							// 所属系统
			return org;
		}
	}

	protected static ContextMapper getDeptContextMapper() {

		return new DeptContextMapper ();
	}

	protected static ContextMapper getPersonContextMapper() {

		return new PersonContextMapper ();
	}

//	public static void main(String[] args) {
//		LdapUtils ldapUtils = new LdapUtils ();
//
//
//
//		LdapDept dept =new LdapDept ();
//		try {
//			dept = ldapUtils.getDeptByOU ( "ou=10000001,cn=dept,dc=cctv,dc=com" );
//		}
//		catch (NamingException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		System.out.println ( dept );
//	}

	/**
	 * ��ȡ������Ա��Ϣ
	 * 
	 * @return
	 */
	public List getAllPersons() {
		List personList = new ArrayList ();
		AndFilter filter = new AndFilter ();
		filter.and ( new EqualsFilter ( "objectclass", "person" ) ); // ��Ӳ�ѯ����
		personList = personLdapTemplate.search ( DistinguishedName.EMPTY_PATH,
				filter.encode (), getPersonContextMapper () );
		return personList;
	}

	/**
	 * ��ȡ������֯����
	 * 
	 * @return
	 */
	public List getAllDept() {
		List deptList = new ArrayList ();
		AndFilter filter = new AndFilter ();
		filter.and ( new EqualsFilter ( "objectclass", "organizationalUnit" ) );
		deptList = deptLdapTemplate.search ( DistinguishedName.EMPTY_PATH,
				filter.encode (), LdapDept.getMapper () );
		return deptList;
	}

	/**
	 * �����Աuid��ѯ��Ա����ϸ��Ϣ
	 * 
	 * @param uid
	 * @return
	 */
	public LdapPerson getPersonByUID(String uid) {
		DistinguishedName dn = new DistinguishedName ();
		dn.append ( "uid", uid );
		return (LdapPerson) personLdapTemplate.lookup ( dn, new PersonContextMapper () );
	}
	public LdapDept getDeptByUID(String dn) {
//		DistinguishedName dn = new DistinguishedName ();
//		dn.append ( "uid", uid );
		return (LdapDept) deptLdapTemplate.lookup ( dn, new DeptContextMapper () );
	}
	/**
	 * ��ݲ���OU ��ѯ������Ϣ
	 * 
	 * @param ou
	 * @return
	 * @throws Exception 
	 */
	public List getDeptByOU(String ou)throws Exception{
		List list = new  ArrayList();
		list = deptLdapTemplate.search (ou, "ou=*", SearchControls.SUBTREE_SCOPE, LdapDept.getMapper () );
		return list;
		
	}
	
	/** ��֤
	 * 
	 * @param uid
	 * @param psw
	 * @return
	 * @throws Exception
	 */
	public boolean authenticate(String uid, String psw)throws Exception {
		return personLdapTemplate.authenticate(DistinguishedName.EMPTY_PATH, "(uid="
				+ uid + ")", psw);
	}
	
	/**
	 * ��ݵ�ǰ����ou���ҳ����¼�ou
	 * ou=XXXXXX,ou=xxxxxxx,ou=xxxxxxx
	 */
	public String searchOrgOU(String orgCode)throws Exception{
		if(orgCode==null || "".equals(orgCode)){
			return null;
		}
		return "";
//		AndFilter filter = new AndFilter ();
//		filter.and ( new EqualsFilter ( "ou", orgCode) );
//		SearchControls ctls = new SearchControls();
//		ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
//		NamingEnumeration<SearchResult> enumera = deptLdapTemplate.getContextSource()
//			.getReadOnlyContext().search(DistinguishedName.EMPTY_PATH, filter.encode (), ctls);
//		if(enumera.hasMore()){
//			return enumera.nextElement().getNameInNamespace ();	// ��ȡȫ��
//		}else{
//			throw new Exception("δ�ҵ��ò���:" + orgCode);
//		}
	}
	
	/**
	 * ��ѯ��ǰOU�����ַ�������ʾ��<br/>
	 * <code>ou=xxxxxxxx,cn=dept,dc=cctv,dc=com</code>
	 */
	public String searchCurrentOU(String orgCode, String orgMaster) throws Exception{
		String dnStr = "";
		String finalDN = "ou=" + orgCode + "$ou$," + BASE_DN;
		/**
		 * ���ڶ�����������ϻ�
		 */
		if(orgMaster!=null && !"".equals(orgMaster) && !"10000000".equals( orgMaster)){
			String orgMasterOU = searchOrgOU(orgMaster);
			dnStr =	","+ orgMasterOU;
		}else{
			/**
			 * ���� ���� ���� Ƶ��
			 * ou=xxxxxxxx,cn=dept,dc=cctv,dc=com
			 */
			dnStr = "";
		}
//		finalDN = finalDN.replace("$ou$", dnStr);
		finalDN = searchOrgOU(orgMaster);
		return finalDN;
	}
}
